package com.apes.hr.salary.rewardPunish.service;


import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.mq.annotation.Consumer;
import com.apes.framework.util.MapUtil;
import com.apes.hr.base.model.Employee;
import com.apes.hr.base.model.TransferRecord;
import com.apes.hr.base.repository.EmployeeRepository;
import com.apes.hr.base.repository.TransferRecordRepository;
import com.apes.hr.recruit.repository.ApplyJobOrderRepository;
import com.apes.hr.salary.rewardPunish.model.*;
import com.apes.hr.salary.rewardPunish.repository.RewardPunishRepository;
import com.apes.hr.salary.rewardPunish.repository.TeamRewardPunishItemRepository;
import com.apes.hr.salary.rewardPunish.repository.TeamRewardPunishPreRepository;
import com.apes.hr.transfer.model.TransferApplicationItem;
import com.apes.hr.transfer.repository.TransferApplicationItemRepository;
import com.apes.scm.masterdata.frame.model.Branch;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.BranchRepository;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.rbac.model.Post;
import com.apes.scm.rbac.repository.PostRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 功能：集体奖惩前置记录单服务
 *
 * @author linwz
 * @create 2019-02-27 09:55
 */
@Service("teamRewardPunishPreService")
public class TeamRewardPunishPreService extends DomainService {

    @Autowired
    TeamRewardPunishItemRepository teamRewardPunishItemRepository;
    @Autowired
    BranchRepository branchRepository;
    @Autowired
    TransferRecordRepository transferRecordRepository;
    @Autowired
    ApplyJobOrderRepository applyJobOrderRepository;
    @Autowired
    TransferApplicationItemRepository transferApplicationItemRepository;
    @Autowired
    RewardPunishRepository rewardPunishRepository;
    @Autowired
    EmployeeRepository employeeRepository;
    @Autowired
    PostRepository postRepository;
    @Autowired
    RewardPunishService rewardPunishService;
    @Autowired
    DeptRepository deptRepository;
    @Autowired
    TeamRewardPunishPreRepository teamRewardPunishPreRepository;

    /**
     * 功能：保存集体奖惩记录单
     * @param request
     * @return
     */
    public TeamRewardPunishPre save(SimpleRequest request) {
        TeamRewardPunishPre teamRewardPunishPre = request.getO(TeamRewardPunishPre.class);
        checkAmt(teamRewardPunishPre);
        teamRewardPunishPre.setState("create");
        return teamRewardPunishPreRepository.saveAndFlush(teamRewardPunishPre);
    }

    /**
     * 检查奖励总额和处罚总额分配
     * @param teamRewardPunishPre
     */
    public void checkAmt(TeamRewardPunishPre teamRewardPunishPre){
        double amt  = 0;
        double itemAmt =0;
        double itemPunishAmt =0;
        Set<TeamRewardPunishDistribution> distributionSet = teamRewardPunishPre.getTeamRewardPunishDistributions();
        for (TeamRewardPunishDistribution distribution : distributionSet) {
            amt = distribution.getAmt();
            if (amt>=0){
                itemAmt = itemAmt + amt ;
            }else{
                itemPunishAmt = itemPunishAmt + amt ;
            }
        }
        if (itemAmt> teamRewardPunishPre.getItemAmt())throw new RuntimeException("奖励总额超过!");
        if (itemPunishAmt< teamRewardPunishPre.getItemPunishAmt())throw new RuntimeException("惩罚总额超过!");
    }
    /**
     * 功能：检查数据
     * @param request
     */
    public TeamRewardPunishPre checkData(SimpleRequest request){
        Object oldId = request.get("id");
        String id = String.valueOf(oldId);
//        TeamRewardPunishPre TeamRewardPunishPre = request.getO("id",TeamRewardPunishPre.class);
//        Long id = TeamRewardPunishPre.getId();
        int version = request.get("version");
        TeamRewardPunishPre oldBill = teamRewardPunishPreRepository.findOne(Long.valueOf(id));
        if (oldBill == null) throw new RuntimeException("奖惩记录分配单：" + request.get("id") + " 在系统中不存在。");
        if (oldBill.getVersion() != version ) throw new RuntimeException("记录已更新或已删除，请重新提交！");

        return oldBill;
    }

    /**
     * 功能：修改数据
     * @param request
     * @return
     */
    public TeamRewardPunishPre update(SimpleRequest request){
        TeamRewardPunishPre oldBill = checkData(request);
        TeamRewardPunishPre teamRewardPunishPre = request.getO(TeamRewardPunishPre.class);
        checkAmt(teamRewardPunishPre);

        return teamRewardPunishPreRepository.saveAndFlush(teamRewardPunishPre);
    }

    /**
     * 功能：删除奖惩记录
     * @param request
     * @return
     */
    public String delete(SimpleRequest request) {
        TeamRewardPunishPre oldBill = checkData(request);
        if (oldBill.getApproveDate() != null) throw new RuntimeException("奖惩记录：" + request.get("id") + " 在系统中已审批。");

        oldBill.setState("delete");
        teamRewardPunishPreRepository.saveAndFlush(oldBill);
        return "删除成功！";
    }

    /**
     * 功能：审核奖惩记录
     *
     * @param request
     * @return
     */
    public TeamRewardPunishPre approve(SimpleRequest request) {
        TeamRewardPunishPre oldBill = checkData(request);
        if (oldBill.getApproveDate() != null) throw new RuntimeException("奖惩记录：" + request.get("id") + " 在系统中已审核。");
        TeamRewardPunishPre rewardPunish = request.getO(TeamRewardPunishPre.class);
        rewardPunish.setState("approve");
        rewardPunish.setApproveDate(new Date());
        rewardPunish.setApproveUid(this.getPerson(request));
        return teamRewardPunishPreRepository.saveAndFlush(rewardPunish);
    }

    /**
     * 功能：确定分配
     *
     * @param request
     * @return
     */
    public TeamRewardPunishPre sendOut(SimpleRequest request) {
        TeamRewardPunishPre oldBill = checkData(request);
        if (oldBill.getDistributionDate() != null) throw new RuntimeException("奖惩记录：" + request.get("id") + " 在系统中已确定分配。");
        TeamRewardPunishPre rewardPunish = request.getO(TeamRewardPunishPre.class);
        TeamRewardPunishItem item = teamRewardPunishItemRepository.findOne(rewardPunish.getId());
        item.setState("approve");
        item.setDistributionDate(new Date());
        item.setDistribution(true);
        item.setApproveDate(new Date());
        item.setApproveUid(this.getPerson(request));
        rewardPunish.setState("sendOut");
        rewardPunish.setDistributionDate(new Date());
        rewardPunish.setDistribution(true);
        //确认分配的同时审核
        if (oldBill.getApproveDate() != null) throw new RuntimeException("奖惩记录：" + request.get("id") + " 在系统中已审核。");

        rewardPunish.setState("approve");
        rewardPunish.setApproveDate(new Date());
        rewardPunish.setApproveUid(this.getPerson(request));
        return teamRewardPunishPreRepository.saveAndFlush(rewardPunish);
    }


    /**
     * 生成个人奖惩单
     * @param team
     * @return
     */
    @Consumer(topic = "hr.teamRewardPunish.setRewardPunishItemTwo", backup = false)
    public RewardPunish setRewardPunishItemTwo(SimpleRequest request){
        TeamRewardPunish team = request.getO(TeamRewardPunish.class);
        RewardPunish rewardPunish = new RewardPunish();
        RewardPunishType type = team.getRewardPunishType();
        rewardPunish.setId(team.getId());
        rewardPunish.setExplain(team.getExplain());
        rewardPunish.setSourceOrder(team.getId());
        rewardPunish.setSourceName("集体奖惩单："+ team.getId());
        rewardPunish.setRewardPunishType(type);
        rewardPunish.setQuotaType(type.getQuotaType());
        rewardPunish.setDocNumber(team.getDocNumber());
        rewardPunish.setDocFileName(team.getDocFileName());
        rewardPunish.setState("allocated");
        rewardPunish.setSendOutUid(team.getSendOutUid());
        rewardPunish.setSendOutDate(team.getSendOutDate());
        rewardPunish.setRewardDate(team.getRewardDate());
        rewardPunish.setRewardEndDate(team.getRewardEndDate());
        List<RewardPunishItem> itemSet = new ArrayList<>();
        Set<TeamRewardPunishItem> teamRewardPunishItemSet = team.getTeamRewardPunishItems();
        Set<TeamRewardPunishPre> teamRewardPunishPreSet = new HashSet<>();
        teamRewardPunishItemSet.forEach(teamItem -> {
            TeamRewardPunishPre teamRewardPunishPre = teamRewardPunishPreRepository.findOne(teamItem.getId());
            teamRewardPunishPreSet.add(teamRewardPunishPre);
        });
        teamRewardPunishPreSet.forEach(teamRewardPunishPre -> {
            teamRewardPunishPre.getTeamRewardPunishDistributions().forEach(teamRewardPunishDistribution -> {
                RewardPunishItem item = new RewardPunishItem();
                item.setRewardPunish(rewardPunish);
                if(teamRewardPunishDistribution.getEmployee().getCompany()!=null){
                    item.setCompany(teamRewardPunishDistribution.getEmployee().getCompany());
                }else{
                    List<Dept> deptList = deptRepository.findByBranch(teamRewardPunishDistribution.getWorkBranch());
                    if(!deptList.isEmpty()){
                        item.setCompany(deptList.get(0).getCompany());
                    }else{
                        throw new RuntimeException("员工：" + teamRewardPunishDistribution.getEmployee().getName()+ " 在系统中没有所属公司。");
                    }
                }
                item.setEmployee(teamRewardPunishDistribution.getEmployee());
                item.setWorkBranch(teamRewardPunishDistribution.getWorkBranch());
                item.setWorkPost(teamRewardPunishDistribution.getWorkPost());
                item.setOnDutyState(teamRewardPunishDistribution.getOnDutyState());
                item.setEntryDate(teamRewardPunishDistribution.getEmployee().getEntryDate());
                item.setTransferOn(teamRewardPunishDistribution.getTransferOn());
                item.setTransferOut(teamRewardPunishDistribution.getTransferOut());
                item.setAffordLossAmt(0);
                item.setValue(0);
                item.setQty(1);
                item.setCancelYearBonusMonth(0);
                item.setManageBonusAmt(0);
                item.setCancelManageBonusMonth(0);
                item.setDismiss(false);
                item.setDemotion(false);
                item.setRetain(false);
                item.setReprieve(teamRewardPunishDistribution.isReprieve());
                item.setNoPenalty(teamRewardPunishDistribution.isNoPenalty());
                item.setAmt(teamRewardPunishDistribution.getAmt());
                itemSet.add(item);
            });
        });

        rewardPunish.setRewardPunishItems(itemSet);
        return rewardPunishRepository.saveAndFlush(rewardPunish);
    }



    public TeamRewardPunishPre findOne(SimpleRequest request) throws Exception {
        Integer id = request.get("id") instanceof String ? Integer.valueOf(request.get("id")) : request.get("id");
        return teamRewardPunishPreRepository.findOne( Long.valueOf(id));
    }

    /**
     *  根据门店、事发起、止时间 找出这段时间内在职的人员
     * @param request
     * @return
     */
    public List<TeamRewardPunishDistribution> findEmployee(SimpleRequest request){
        String workBranch =  request.get("workBranch");
        String rewardDate =  request.get("rewardDate");
        String rewardEndDate =  request.get("rewardEndDate");
        RewardPunishType rewardPunishType = request.getO("rewardPunishType",RewardPunishType.class);
        Branch branch = branchRepository.findOne(workBranch);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date reward = new Date();
        Date end = new Date();
        try {
            reward = sdf.parse(rewardDate);
            end = sdf.parse(rewardEndDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        List<TransferRecord> transferRecordList = transferRecordRepository.findByWorkBranchAndTransferOnAndTransferOut(branch,reward,end);

        List<TransferRecord> newTransferRecordList = transferRecordRepository.findByWorkBranch(branch).stream().filter(transferRecord -> transferRecord.getEmployee().getEmployeeState().getId().equals("000088")).collect(Collectors.toList());
        Map<Employee,List<TransferRecord>> empTransferList = newTransferRecordList.stream().sorted(Comparator.comparing(TransferRecord::getTransferOn)).collect(Collectors.groupingBy(TransferRecord::getEmployee));
        List<TransferRecord> transferRecordList1 = screenTransfer(empTransferList,reward,end);
        return setDistribution(transferRecordList1,rewardPunishType,reward,end);
    }
    /**
     * 传入的时间加一天
     * @param date
     * @return
     */
    private Date dateAdd(Date date,int i){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, i);//+1今天的时间加1月
        return calendar.getTime();
    }

    /**
     * 筛选出正确的调动单
     * @param empTransferList
     * @param reward
     * @param end
     * @return
     */
    public  List<TransferRecord> screenTransfer( Map<Employee,List<TransferRecord>> empTransferList,Date reward,Date end){
        List<TransferRecord> transferRecordList1 = new ArrayList<>();
        for (Map.Entry<Employee, List<TransferRecord>> entry : empTransferList.entrySet()){
            List<TransferRecord> transferRecords = entry.getValue();
            for (TransferRecord transferRecord : transferRecords) {
                Date transferOut = transferRecord.getTransferOut();
                Date transferOn = transferRecord.getTransferOn();
                //if 只要调至时间在奖惩期结束前
                if (end.getTime() >= transferOn.getTime()) {
                    // 只要调离时间在奖惩开始后
                    if(transferOut ==null || transferOut.getTime()>= reward.getTime())transferRecordList1.add(transferRecord);
                }
            }
        }

        return transferRecordList1;
    }


    /**
     * 将信息写入分配明细
     * @param transferRecordList
     * @param rewardPunishType
     * @return
     */
    public List<TeamRewardPunishDistribution> setDistribution (List<TransferRecord> transferRecordList,RewardPunishType rewardPunishType,Date reward,Date end) {
        List<TeamRewardPunishDistribution> distributionList = new ArrayList<>();
        transferRecordList.forEach(transferRecord -> {
            TeamRewardPunishDistribution distribution = new TeamRewardPunishDistribution();
            Date transferOn = transferRecord.getTransferOn();
            Employee employee = transferRecord.getEmployee();
            distribution.setEmployee(employee);
            distribution.setAmt(0);
            distribution.setOnDutyState(transferRecord.getOnDutyState());
            distribution.setWorkBranch(transferRecord.getWorkBranch());
            distribution.setWorkPost(transferRecord.getPost());
            distribution.setTransferOn(transferOn);
            distribution.setTransferOut(transferRecord.getTransferOut());
            distribution.setReprieve(false);
            transferOn = setTransferOnDate(transferOn);
            double valueTotal = rewardPunishService.getRewardPunishValue(employee,reward);
            distribution.setEmpValueTotal(valueTotal);
            if(rewardPunishType.getCategory().getDescription().equals("处罚")) {
                String applyJobOrderId = transferRecord.getApplyJobOrderId();
                String transferApplicationItemId = transferRecord.getTransferApplicationItemId();
                if (transferApplicationItemId == null || transferApplicationItemId.isEmpty()) {
                    //新入职两个月内免罚
                    if (reward.before(dateAdd(transferOn, 2))) {
                        distribution.setNoPenalty(true);
                    }
                } else {
                    TransferApplicationItem transferApplicationItem = transferApplicationItemRepository.findOne(Integer.valueOf(transferApplicationItemId));
                    String description = transferApplicationItem.getHrTransferKind().getDescription();
                    String onDutyState = new String();
                    if (transferRecord.getOnDutyState()!=null){
                        onDutyState = transferRecord.getOnDutyState().getDescription();
                    }
                    //调动性质为晋职，当月免罚 ；为平调的，两个月免罚 ；为代理期的，两个月免罚
                    if (description.equals("晋职") && reward.before(dateAdd(transferOn, 1))) {
                        distribution.setNoPenalty(true);
                    } else if (description.equals("平调") && reward.before(dateAdd(transferOn, 2))) {
                        distribution.setNoPenalty(true);
                    } else if (onDutyState.equals("代理期") && reward.before(dateAdd(transferOn, 2))){
                        distribution.setNoPenalty(true);
                    }

                }
            }else {
                distribution.setNoPenalty(false);
            }

            distributionList.add(distribution);
        });
        return distributionList;
    }

    /**
     * 3月1号开始则到4月30号算两个完整自然月。3月2号开始则到5月31号算两个完整自然月
     * @param transferOn
     * @return
     */
    public Date setTransferOnDate(Date transferOn){

        int day = transferOn.getDate();
        if (day !=1 ){
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(transferOn);
            calendar.add(Calendar.MONTH, 1);//+1今天的时间加1月
            calendar.set(Calendar.DAY_OF_MONTH,1);
            transferOn = calendar.getTime();
        }
        return transferOn;
    }

    /**
     * 根据登录的部门查询
     * @return
     */
    public Map findByBranch(SimpleRequest request){
        Post post = postRepository.findOne(request.getPostId());
        List<Map> filters = request.get("condition");
        Branch branch = post.getBranch();
        if (branch.getBranchType().getDescription().equals("销售")){
            JSONObject state = new JSONObject();
            state.put("field", "workBranch");
            state.put("operator", "EQ");
            state.put("value", branch);
            filters.add(state);
        }
        JSONObject teamState = new JSONObject();
        teamState.put("field", "teamRewardPunish.state");
        teamState.put("operator", "EQ");
        teamState.put("value", "approve");
        filters.add(teamState);
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        return MapUtil.mapped(teamRewardPunishPreRepository.findAll(JpaDsl.toCriteria(filters),PageRequest.of(request.get("page"), request.get("size"), sort)),"teamRewardPunishDistributions");
//
    }

    /**
     * date转localDate
     * @param date
     * @return
     */
    public static LocalDate DateToLocaleDate(Date date) {
        Instant instant = date.toInstant();
        ZoneId zoneId  = ZoneId.systemDefault();
        return instant.atZone(zoneId).toLocalDate();
    }

}
